﻿package com.guavestudios.fnfo {
	import com.adobe.images.JPGEncoder;
	import com.guavestudios.fnfo.api.IFnfoPlugin;
	import com.guavestudios.fnfo.plugins.*;
	import com.guavestudios.utils.Format;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	
	/**
	 * Fnfo facade for all functionality
	 * @author maze | guavestudios.com
	 */
	public class Fnfo extends Sprite {
		
		protected static var instance:Fnfo;
		
		
		public static const SHOW:String= "Fnfo.SHOW";
		public static const HIDE:String = "Fnfo.HIDE";
		public static const DISPLAY_DATA:String = "Fnfo.DISPLAY_DATA";
		public static const GATHER_DATA:String = "Fnfo.GATHER_DATA";
		public static const INITIALIZE:String = "Fnfo.INITIALIZE";
		public static const RESIZE:String= "Fnfo.RESIZE";
		
		/**
		 * Initialize fnfo with parameters
		 * @param	container	container to listen (must be a interactive object like the application)
		 * @param	data	additional parameters for plugins
		 */
		public static function initialize(container:InteractiveObject,data:Object):void {
			getInstance().init(container,data);
		}
		/**
		 * get the instance of fnfo (Singelton)
		 * @return
		 */
		public static function getInstance():Fnfo {
			if (instance == null) {
				instance = new Fnfo(new SingletonLock());
			}
			return instance;
		}

		
		protected var _size:Rectangle;
		protected var _data:Object;
		protected var _context:ContextMenu;
		protected var _container:InteractiveObject;
		protected var info:TextField;
		protected var _infoList:Array;
		
		protected var _pluginsMap:Object;
		
		public function Fnfo(singletonLock:SingletonLock) {
			this.visible = false;
		}
		/**
		 * init the fnfo with custom data
		 * @param	container
		 * @param	data
		 */
		public function init(container:InteractiveObject,data:Object):void {
			//store
			this._container = container;
			this._data = data;
			this._infoList = new Array();
			
			//set size
			_size = new Rectangle(0, 0, _container.stage.stageWidth, _container.stage.stageHeight);
			
			//read plugins
			_pluginsMap = new Object();
			addPlugin(new FnfoVersionInfo());
			addPlugin(new FlashVersionInfo());
			addPlugin(new FnfoScreenshot());
			addPlugin(new LastErrorPlugin());
			addPlugin(new FlashFileParametersInfo());
			addPlugin(new ButtonBarDisplay());
			
			addPlugin(new BasicTextDataDisplay());
			if (_data.hasOwnProperty("plugins")) {
				var a:Array = _data["plugins"] as Array;
				if (a != null) {
					//add plugins
					for (var i:int = 0,ilen:int=a.length; i < ilen; i++) {
						var c:Class = a[i];
						addPlugin(new c());
					}
				}
			}
			
			//add context menu
			var ctx:ContextMenu = _container.contextMenu;
			if (ctx == null) ctx = new ContextMenu();
			
			var items:Array = ctx.customItems;
			if (items == null) items = [];
			
			var ctxm:ContextMenuItem = new ContextMenuItem("fnfo");
			ctxm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, context_selected);
			items.push(ctxm);
			
			ctx.customItems = items;
			_container.contextMenu = ctx;
			_context = ctx;
			
			//init graphics
			initGraphics();
			
			dispatchEvent(new Event(INITIALIZE));
			
			draw();
		}
		/**
		 * show fnfo
		 */
		public function show():void {
			
			dispatchEvent(new Event(SHOW));
			
			this.visible = true;
			initData();
			container.stage.addChild(this);
			container.stage.addEventListener(Event.RESIZE, stage_resize);
		}
		
		/**
		 * hide fnfo
		 */
		public function hide():void {
			dispatchEvent(new Event(HIDE));
			
			this.visible = false;
			_container.stage.removeChild(this);
			_container.stage.removeEventListener(Event.RESIZE, stage_resize);
		}
		/**
		 * Is the actual form shown
		 * @return	Shown or not
		 */
		public function isShow():Boolean {
			return this.visible;
		}
		
		private function context_selected(e:ContextMenuEvent):void {
			if (this.visible) hide();
			else show();
		}
		
		private function initData():void {
			_infoList = [];
			
			dispatchEvent(new Event(GATHER_DATA));
			
			dispatchEvent(new Event(DISPLAY_DATA));
			
		}
		private function initGraphics():void{
			
		}
		
		private function draw():void {
			this.graphics.clear();
			this.graphics.beginFill(0);
			this.graphics.drawRect(0,0,_size.width, _size.height);
			this.graphics.endFill();
		}
		private function stage_resize(e:Event):void {
			_size.width = _container.stage.stageWidth;
			_size.height = _container.stage.stageHeight;
			setSize(_size);
		}
		public function printInfo(desc:String, value:String):void {
			_infoList.push({desc:desc,value:value});
		}
		public function addPlugin(plug:IFnfoPlugin):void {
			_pluginsMap[plug.pluginId]=plug;
			plug.initPlugin(this);
		}
		public function getPluginById(id:String):IFnfoPlugin {
			return _pluginsMap[id];
		}
		public function hasPluginById(id:String):Boolean {
			return _pluginsMap.hasOwnProperty(id);
		}
		
		public function get data():Object { return _data; }
		public function get context():ContextMenu { return _context; }
		public function get container():InteractiveObject { return _container; }
		
		public function get infoList():Array { return _infoList; }
		
		public function set infoList(value:Array):void {
			_infoList = value;
		}
		
		public function getSize():Rectangle { return _size; }
		public function setSize(value:Rectangle):void {
			_size = value;
			draw();
			dispatchEvent(new Event(RESIZE));
		}

	}
	
}
class SingletonLock {}